﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using TomVanGaever.BCS.Parser;
using System.Windows.Forms;
using System.IO;
using System.Xml.Linq;
using System.EnterpriseServices.Internal;

namespace TomVanGaever.BCS.Parser
{
    public class BCSParserUtility
    {
        private const string m_dllnotfound = "The system could not find the dll for this project at '{0}'. Did you build the project?";

        public static void Update(DirectoryInfo folder_GAC)
        {
            if (!folder_GAC.Exists)
            return;

            foreach (FileInfo dll in folder_GAC.GetFiles("*.dll"))
                Update(dll);
    }

        public static void Update(FileInfo dll)
        {
            Publish objpublish = new Publish();
            objpublish.GacRemove(dll.FullName);
            objpublish.GacInstall(dll.FullName);
        }

        public static void Initiate(string dlllocation)
        {
            FileInfo dll = new FileInfo(dlllocation);
            bool exists = dll.Exists;
            if (!exists) throw new ArgumentException(string.Format(m_dllnotfound, dlllocation));
            Update(dll);
			try
			{
				AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve +=
						new ResolveEventHandler(CurrentDomain_ReflectionOnlyAssemblyResolve);

				Assembly assembly = Assembly.ReflectionOnlyLoadFrom(dlllocation);
				Init(assembly, dlllocation);
			}
			catch (Exception ex) {
				throw new InvalidOperationException(string.Format("unable to load assembly from '{0}'", dlllocation),ex);
			}
        }

        private void LoadAnAssembly(Assembly assembly, string sourcelocation)
          {
                    byte[] assemblyRaw = FileIntoBytes(sourcelocation);
                    string assemblyDirecyory = System.IO.Path.GetDirectoryName(sourcelocation);

                    AppDomainSetup tempDomainSetup = new AppDomainSetup();                
                    tempDomainSetup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
                    tempDomainSetup.ApplicationName = "BCSVSIX";

                    AppDomain tempDomain = AppDomain.CreateDomain("tempDomain", null, tempDomainSetup);                
                    Assembly asm = tempDomain.Load(assemblyRaw);
                    Init(assembly, sourcelocation);
                    AppDomain.Unload(tempDomain); 
          }

        private byte[] FileIntoBytes(string filePath)
        {
            System.IO.FileStream fs = new System.IO.FileStream(filePath, System.IO.FileMode.Open);
            byte[] buffer = new byte[(int)fs.Length];
            fs.Read(buffer, 0, buffer.Length);
            fs.Close();
            return buffer;
        } 

        public static void Initiate(Assembly assembly, string sourcelocation)
        {
            Init(assembly, sourcelocation);
        }

        private static void Init(Assembly assembly, string sourcelocation)
        {
            var typesFromAssembly = assembly.GetTypes().Where(t => t.Name.Contains("<") == false).OrderBy(t => t.Name).ToList();

            //Create parser form
            ParserForm form = new ParserForm();
            IBCSParser parser = new BCSParser();

            //Entity Picker
            BCSParserEntityPickerControl entityPicker = new BCSParserEntityPickerControl();
            entityPicker.DataSource = typesFromAssembly;
            entityPicker.DataBind();
            form.BCScontrols.Add(entityPicker);

            //EntityService Picker
            BCSParserEntityServicePickerControl entityServicePicker = new BCSParserEntityServicePickerControl();
            entityServicePicker.DataSource = typesFromAssembly;
            entityServicePicker.DataBind();
            form.BCScontrols.Add(entityServicePicker);

            //EntityIdentifier Picker
            BCSParserEntityIdentifierPickerControl entityIdentifierPicker = new BCSParserEntityIdentifierPickerControl();
            entityIdentifierPicker.GetSelectedEntityType(() => entityPicker.SelectedType);
            entityIdentifierPicker.TypeMember = "FullName";
            form.BCScontrols.Add(entityIdentifierPicker);

            //EntityIdentifier Picker
            BCSParserEntityPropertyPickerControl entityPropertyPicker = new BCSParserEntityPropertyPickerControl();
            entityPropertyPicker.GetSelectedEntityType(() => entityPicker.SelectedType);
            entityPropertyPicker.GetSelectedEntityIdentifier(() => entityIdentifierPicker.SelectedEntityProperty);
            entityPropertyPicker.TypeMember = "FullName";
            form.BCScontrols.Add(entityPropertyPicker);

            //finder capabilities
			BCSParserFilterControl filtercontrol = new BCSParserFilterControl();
			form.BCScontrols.Add(filtercontrol);

            //search capabilities
            BCSParserSearchControl searchcontrol = new BCSParserSearchControl();
            form.BCScontrols.Add(searchcontrol);

            //create capabilities
			BCSParserCreatorControl createcontrol = new BCSParserCreatorControl();
			form.BCScontrols.Add(createcontrol);

            //update capabilities
            BCSParserUpdateControl updatecontrol = new BCSParserUpdateControl();
            form.BCScontrols.Add(updatecontrol);

            //delete capabilities
            BCSParserDeleteControl deletecontrol = new BCSParserDeleteControl();
            form.BCScontrols.Add(deletecontrol);

            //Validation
            BCSParserCheckControl validationcontrol = new BCSParserCheckControl(form.BCScontrols);
            form.BCScontrols.Add(validationcontrol);


            //Finish button
            validationcontrol.BtnFinish.Click += new EventHandler(
                delegate(object sender, EventArgs args)
                {

                    //check if filter capabilities are activitated
                    parser.IsFilterCapabilitiesEnabled = filtercontrol.IsFilterCapabilitiesActivitated();
                    parser.IsCreateCapabilitiesActivitated = createcontrol.IsCreateCapabilitiesActivitated();
                    parser.IsSearchCapabilitiesActivitated = searchcontrol.IsSearchCapabilitiesActivitated();
                    parser.IsUpdateCapabilitiesActivitated = updatecontrol.IsUpdatedCapabilitiesActivitated();
                    parser.IsDeleteCapabilitiesActivitated = deletecontrol.IsDeleteCapabilitiesActivitated();

                    parser.Load(
                        entityPicker.SelectedType,
                        entityServicePicker.SelectedType,
                        entityIdentifierPicker.SelectedEntityProperty,
                        entityPropertyPicker.GetSelectedEntityProperties()
                        );

                    SaveFileDialog open = new SaveFileDialog();
                    open.InitialDirectory = new FileInfo(sourcelocation).Directory.Parent.Parent.FullName;
                    open.Filter = "*.bdcm (Sharepoint Business Data Catalog Model file)|*.bdcm";
                    if (open.ShowDialog() == DialogResult.OK)
                    {
                        if (File.Exists(open.FileName))
                        {
                            Version pv = BCSParser.GetVersion(open.FileName);
                            Version newversion = new Version(pv.Major, pv.Minor, pv.Build, pv.Revision + 1);
                            parser.SetVersion(newversion);
                        }
                        parser.Save(open.FileName);
                        ParserForm.NextButton.Visible = false;
                        ParserForm.PreviousButton.Visible = false;
                        ParserForm.BCSCancelButton.Text = "Close";
                    }
                    form.Close();
                });

            Application.Run(form);
        }

        private static Assembly CurrentDomain_ReflectionOnlyAssemblyResolve(object sender, ResolveEventArgs args)
        {
            return System.Reflection.Assembly.ReflectionOnlyLoad(args.Name);
        }

    }
}
